home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / cmds / fsinstall / fsmake.c < prev    next >
C/C++ Source or Header  |  1992-04-14  |  67KB  |  2,391 lines

  1. /* 
  2.  * fsmake.c --
  3.  *
  4.  *    Make a sprite file system on a raw disk.
  5.  *
  6.  * IMPORTANT NOTE ABOUT PORTABILITY:
  7.  *
  8.  *    I use the sprite directory format even when I am reading a UNIX
  9.  *    directory.  I can get a way with this because they are the same.  The
  10.  *    reason why I don't use the UNIX one is that on a PMAX there are some
  11.  *    defines in "/usr/include/sys/dir.h" which screw up the compilation
  12.  *    of this file.  If this runs on a UNIX system that does not have
  13.  *    a compatible directory format then the code in CopyTree must be
  14.  *    modified.
  15.  *
  16.  * Copyright (C) 1989 by Digital Equipment Corporation, Maynard MA
  17.  *
  18.  *            All Rights Reserved
  19.  *
  20.  * Permission to use, copy, modify, and distribute this software and its 
  21.  * documentation for any purpose and without fee is hereby granted, 
  22.  * provided that the above copyright notice appear in all copies and that
  23.  * both that copyright notice and this permission notice appear in 
  24.  * supporting documentation, and that the name of Digital not be
  25.  * used in advertising or publicity pertaining to distribution of the
  26.  * software without specific, written prior permission.  
  27.  *
  28.  * Digitial disclaims all warranties with regard to this software, including
  29.  * all implied warranties of merchantability and fitness.  In no event shall
  30.  * Digital be liable for any special, indirect or consequential damages or
  31.  * any damages whatsoever resulting from loss of use, data or profits,
  32.  * whether in an action of contract, negligence or other tortious action,
  33.  * arising out of or in connection with the use or performance of this
  34.  * software.
  35.  */
  36.  
  37. #ifndef lint
  38. static char rcsid[] = "$Header: /sprite/src/admin/fsinstall/RCS/fsmake.c,v 1.14 90/02/17 23:47:50 nelson Exp $ SPRITE (Berkeley)";
  39. #endif
  40.  
  41. #include "sprite.h"
  42. #include "option.h"
  43. #include "disk.h"
  44. #include <stdio.h>
  45. #include <sys/file.h>
  46. #include <stdlib.h>
  47. #include <string.h>
  48. #include <sys/types.h>
  49. #include <sys/stat.h>
  50. #include <sys/dir.h>
  51. #include <assert.h>
  52. #include <sys/time.h>
  53.  
  54. #ifdef direct
  55. #undef direct
  56. #endif
  57.  
  58. #if defined(sprite) || defined(sun)
  59. #define S_GFDIR     S_IFDIR
  60. #define S_GFMT      S_IFMT
  61. #define S_GFLNK     S_IFLNK
  62. #define S_GFREG      S_IFREG
  63. #endif
  64.  
  65. /*
  66.  * Constants settable via the command line.
  67.  */
  68. int kbytesToFileDesc = 4;    /* The ratio of kbytes to
  69.                  * the number of file descriptors */
  70. Boolean printOnly = FALSE;    /* Stop after computing the domain header
  71.                  * and just print it out. No disk writes */
  72. Boolean overlapBlocks = FALSE;    /* Allow filesystem blocks to overlap track
  73.                  * boundaries.  Some disk systems can't deal. */
  74. char *deviceName;        /* Set to "rsd0" or "rxy1", etc. */
  75. char *partName;            /* Set to "a", "b", "c" ... "g" */
  76. char defaultFirstPartName[] = "a";
  77. char *diskType = NULL;        /* Type of disk (e.g. rz23) */
  78. int  spriteID = 1;        /* This machines sprite id. */
  79. char *devFileName = NULL;    /* Name of file that contains devices to 
  80.                  * create. */
  81. char *dirName = NULL;        /* Name of directory that contains files to
  82.                  * copy to the disk. */
  83. Boolean newLabel = FALSE;
  84.  
  85. Option optionArray[] = {
  86.     {OPT_STRING, "dev", (Address)&deviceName,
  87.     "Required: Name of device, eg \"rsd0\" or \"rxy1\""},
  88.     {OPT_STRING, "part", (Address)&partName,
  89.     "Required: Partition ID: (a, b, c, d, e, f, g)"},
  90.     {OPT_TRUE, "overlap", (Address)&overlapBlocks,
  91.     "Overlap filesystem blocks across track boundaries (FALSE)"},
  92.     {OPT_INT, "ratio", (Address)&kbytesToFileDesc,
  93.     "Ratio of Kbytes to file descriptors (4)"},
  94.     {OPT_TRUE, "test", (Address)&printOnly,
  95.     "Test: print results, don't write disk (FALSE)"},
  96.     {OPT_FALSE, "write", (Address)&printOnly,
  97.     "Write the disk (TRUE)"},
  98.     {OPT_STRING, "type", (Address)&diskType,
  99.     "Type of disk.  Used to look up disk info in /etc/disktab"},
  100.     {OPT_INT, "sid", (Address)&spriteID,
  101.     "Sprite ID of this workstation"},
  102.     {OPT_STRING, "dir", (Address)&dirName,
  103.     "Directory to copy files from"},
  104.     {OPT_STRING, "devFile", (Address)&devFileName,
  105.     "File that contains devices to create"},
  106.     {OPT_TRUE, "newLabel", (Address)&newLabel,
  107.     "Overwrite the current label on the disk if there is one"},
  108. };
  109. int numOptions = sizeof(optionArray) / sizeof(Option);
  110.  
  111. /*
  112.  * Structure used to peruse Sprite directories.
  113.  */
  114. typedef struct DirIndexInfo {
  115.     Fsdm_FileDescriptor *fdPtr;                  /* The file descriptor being
  116.                           * read. */
  117.     int         blockNum;             /* Block that is being read, 
  118.                           * written, or allocated. */
  119.     int         blockAddr;             /* Address of directory block
  120.                           * to read. */
  121.     int         dirOffset;             /* Offset of the directory entry 
  122.                           * that we are currently examining 
  123.                           * in the directory. */
  124.     char     dirBlock[FS_BLOCK_SIZE];    /* Where directory data is 
  125.                           * stored. */
  126. } DirIndexInfo;
  127.  
  128. /*
  129.  * Time of day when this program runs.
  130.  */
  131.  
  132. struct timeval curTime;
  133.  
  134. /*
  135.  * Forward Declarations.
  136.  */
  137. void        SetSummaryInfo();
  138. void        SetDomainHeader();
  139. void        SetDiskGeometry();
  140. void        SetDomainParts();
  141. void        WriteAllFileDescs();
  142. void        WriteAndInitDataBitmap();
  143. unsigned char    *ReadFileDescBitmap();
  144. void        WriteFileDescBitmap();
  145. unsigned char    *ReadBitmap();
  146. void        WriteBitmap();
  147. char         *MakeFileDescBitmap();
  148. Disk_Info    *ScanDiskTab();
  149. static Fslcl_DirEntry    *OpenDir();
  150. Fslcl_DirEntry    *NextDirEntry();
  151. static void        CloseDir();
  152. Fslcl_DirEntry    *AddToDirectory();
  153. void        CreateDir();
  154. void        MarkDataBitmap();
  155. void        InitDesc();
  156. void        CopyTree();
  157. void        ReadFileDesc();
  158. void        WriteFileDesc();
  159. void        MakeDevices();
  160. void        WriteRootDirectory();
  161.  
  162. /*
  163.  * Macro to get a pointer into the bit map for a particular block.
  164.  */
  165. #define BlockToCylinder(domainPtr, blockNum) \
  166.     (blockNum) / (domainPtr)->geometry.blocksPerCylinder
  167.  
  168. #define GetBitmapPtr(domainPtr, bitmapPtr, blockNum) \
  169.   &((bitmapPtr)[BlockToCylinder(domainPtr, blockNum) * \
  170.   bytesPerCylinder + (blockNum) % (domainPtr)->geometry.blocksPerCylinder / 2])
  171.  
  172. /*
  173.  * Macros to convert physical block numbers to virtual block numbers. All direct
  174.  * blocks are virtual, indirect blocks are physical.
  175.  */
  176. #define VirtToPhys(blockNum) \
  177.     ((blockNum) + (domainPtr)->dataOffset * FS_FRAGMENTS_PER_BLOCK)
  178.  
  179. #define PhysToVirt(domainPtr,blockNum) \
  180.     ((blockNum) - (domainPtr)->dataOffset * FS_FRAGMENTS_PER_BLOCK)
  181.  
  182. /*
  183.  * Macro to mark the file descriptor bit map.
  184.  */
  185. #define MarkFDBitmap(num,bitmapPtr) \
  186.     (bitmapPtr)[(num) >> 3] |= (1 << (7 -((num)  & 7)))
  187.  
  188. int            freeFDNum;    /* The currently free file descriptor.*/
  189. int            freeBlockNum;    /* The currently free data block. */
  190. Fsdm_FileDescriptor    devFD;        /* The file descriptor for the dev
  191.                          * directory. */
  192. Fsdm_FileDescriptor    *devFDPtr;    /* Pointer to the file descriptor for
  193.                      * the dev directory. */
  194. int            devFDNum;    /* The file number of the dev 
  195.                      * directory. */
  196. int            partFID;    /* The file id of the partition that
  197.                      * we are initializing. */
  198. Fsdm_DomainHeader         *domainPtr;    /* The domain the we are initializing.*/
  199. int            partition;    /* The partition that we are 
  200.                      * initializing. */
  201. Disk_Info        *diskInfoPtr;    /* Information about the disk that
  202.                      * we are initializing. */
  203. Fsdm_SummaryInfo         *summaryPtr;    /* Summary information for the domain.*/
  204. unsigned char        *fdBitmapPtr;    /* Pointer to the file descriptor
  205.                      * bitmap. */
  206. unsigned char        *cylBitmapPtr;    /* Pointer to the cylinder bit map. */
  207. int            bytesPerCylinder;/* The number of bytes in
  208.                       * the bitmap for a cylinder.*/
  209.  
  210.  
  211.  
  212. /*
  213.  * Some number of sectors in the root partition must be allocated to the
  214.  * boot program. The default is for the new filesystem to have the same
  215.  * number of boot sectors as the old filesystem. If the disk did not
  216.  * previously have a filesystem, or if the domain header cannot be found,
  217.  * then the following number of boot sectors are allocated. The standard
  218.  * Sun format is for the summary sector to be in sector #17. 16 boot sectors
  219.  * and one disk label fill the first 17 sectors.
  220.  */
  221. int    defaultBootSectors = 16;
  222.  
  223. int bootSectors = -1;
  224.  
  225.  
  226. /*
  227.  *----------------------------------------------------------------------
  228.  *
  229.  * main --
  230.  *
  231.  *    Create the required file names from the command line
  232.  *    arguments.  Then open the first partition on the disk
  233.  *    because it contains the disk label, and open the partition
  234.  *    that is to be formatted.
  235.  *
  236.  * Results:
  237.  *    None.
  238.  *
  239.  * Side effects:
  240.  *    Calls MakeFilesystem
  241.  *
  242.  *----------------------------------------------------------------------
  243.  */
  244. main(argc, argv)
  245.     int        argc;
  246.     char    *argv[];
  247. {
  248.     char    answer[10];
  249.     char    partitionName[64];
  250.     int        status;
  251.     static      char block[DEV_BYTES_PER_SECTOR];
  252.     int         i;
  253.  
  254.     gettimeofday(&curTime, NULL);
  255.  
  256.     (void)Opt_Parse(argc, argv, optionArray, numOptions, 0);
  257.  
  258.     if (deviceName == (char *)0) {
  259.     fprintf(stderr,"Specify device name with -dev option\n");
  260.     exit(1);
  261.     }
  262.     if (partName == (char *)0) {
  263.     fprintf(stderr,"Specify partition with -part option\n");
  264.     exit(1);
  265.     } 
  266.     if (spriteID == 0) {
  267.     fprintf(stderr, "Specify sprite id with -sid option\n");
  268.     exit(1);
  269.     }
  270.  
  271.     bootSectors = defaultBootSectors;
  272.  
  273.     if (!printOnly) {
  274.     printf("The \"-write\" option will cause fsmake to overwrite the current filesystem.\nDo you really want to do this?[y/n] ");
  275.     if (scanf("%10s",answer) != 1) {
  276.         exit(0);
  277.     }
  278.     if ((*answer != 'y') && (*answer != 'Y')) {
  279.         exit(0);
  280.     }
  281.     }
  282.  
  283.     if (partName[0] != 'a' && partName[0] != 'c') {
  284.     fprintf(stderr, "Can only format partitions a or c\n");
  285.     exit(1);
  286.     }
  287.  
  288.     /*
  289.      * Gen up the name of the first partition on the disk.
  290.      */
  291.     sprintf(partitionName, "/dev/%s%s", deviceName, partName);
  292.  
  293.     if (printOnly) {
  294.     partFID = open(partitionName, O_RDONLY);
  295.     } else {
  296.     partFID = open(partitionName, O_RDWR);
  297.     }
  298.     if (partFID < 0 ) {
  299.     perror("Can't open first partition");
  300.     exit(1);
  301.     }
  302.  
  303.     printf("fsmake based on 4K filesystem blocks\n");
  304.  
  305.     partition = partName[0] - 'a';
  306.  
  307.     diskInfoPtr = NULL;
  308.     if (!newLabel) {
  309.     /*
  310.      * See if we can read the copy of the super block at the beginning
  311.      * of the partition to find out basic disk geometry and where to
  312.      * write the domain header.  This will only work with disks that
  313.      * have either a sun label or a sprite label.
  314.      */
  315.     diskInfoPtr = Disk_ReadDiskInfo(partFID, partition);
  316.     }
  317.     if (diskInfoPtr == NULL && diskType != NULL) {
  318.     /*
  319.      * See if we can find the information in /etc/disktab.
  320.      */
  321.     diskInfoPtr = ScanDiskTab();
  322.     }
  323.     if (diskInfoPtr == NULL) {
  324.     fprintf(stderr,"MakeFilesystem: Unable to read super block.\n");
  325.     return(1);
  326.     }
  327.  
  328.     /*
  329.      * Clear out the old summary sector and domain header. This is especially
  330.      * important if we are going to move them.
  331.      */
  332.     if ((!printOnly) && (diskInfoPtr->summarySector != -1)) {
  333.     status = Disk_SectorWrite(partFID, diskInfoPtr->summarySector,1, block);
  334.     if (status != SUCCESS) {
  335.         perror("Clear of old summary sector failed"); 
  336.         return(status);
  337.     }
  338.     for (i = 0; i < diskInfoPtr->numDomainSectors; i++) {
  339.         status = Disk_SectorWrite(partFID, diskInfoPtr->domainSector+i,
  340.                 1, block);
  341.         if (status != SUCCESS) {
  342.         perror("Clear of old domain header failed"); 
  343.         return(status);
  344.         }
  345.     }
  346.     }
  347.     /* 
  348.      * The disk did not previously have a filesystem on it.
  349.      */
  350.     if (diskInfoPtr->summarySector == -1) {
  351.     diskInfoPtr->summarySector = bootSectors + 1;
  352.     diskInfoPtr->domainSector = bootSectors + 2;
  353.     }
  354.     domainPtr = (Fsdm_DomainHeader *)
  355.     malloc((unsigned) diskInfoPtr->numDomainSectors * DEV_BYTES_PER_SECTOR);
  356.     SetDomainHeader();
  357.     bytesPerCylinder = (domainPtr->geometry.blocksPerCylinder + 1) / 2;
  358.     Disk_PrintDomainHeader(domainPtr);
  359.  
  360.     if (!printOnly) {
  361.     assert(diskInfoPtr->domainSector >= 0);
  362.     status = Disk_SectorWrite(partFID, diskInfoPtr->domainSector,
  363.                 diskInfoPtr->numDomainSectors, (Address)domainPtr);
  364.     if (status != 0) {
  365.         perror("DomainHeader write failed");
  366.         return(status);
  367.     }
  368.     }
  369.  
  370.     summaryPtr = (Fsdm_SummaryInfo *) malloc(DEV_BYTES_PER_SECTOR);
  371.     SetSummaryInfo();
  372.     Disk_PrintSummaryInfo(summaryPtr);
  373.     if (!printOnly) {
  374.     assert(diskInfoPtr->summarySector >= 0);
  375.     status = Disk_SectorWrite(partFID, diskInfoPtr->summarySector, 1,
  376.                 (Address)summaryPtr);
  377.     if (status != 0) {
  378.         perror("Summary sector write failed");
  379.         return(status);
  380.     }
  381.     }
  382.  
  383.     WriteAllFileDescs();
  384.     WriteAndInitDataBitmap();
  385.     WriteRootDirectory();
  386.  
  387.     /*
  388.      * We now have a good empty file system.  Add any files and devices
  389.      * that need to be added.
  390.      */
  391.     if (dirName != NULL) {
  392.     Fsdm_FileDescriptor    rootDesc;
  393.  
  394.     fdBitmapPtr = ReadFileDescBitmap();
  395.     freeFDNum = 3;
  396.     cylBitmapPtr = ReadBitmap();
  397.     freeBlockNum = 1;
  398.     ReadFileDesc(FSDM_ROOT_FILE_NUMBER, &rootDesc);
  399.     CopyTree(dirName, FSDM_ROOT_FILE_NUMBER, &rootDesc,
  400.         FSDM_ROOT_FILE_NUMBER, FALSE, "/");
  401.     WriteFileDesc(FSDM_ROOT_FILE_NUMBER, &rootDesc);
  402.     if (devFileName != NULL) {
  403.         if (devFDPtr == NULL) {
  404.         fprintf(stderr, "Couldn't find /dev\n");
  405.         exit(1);
  406.         }
  407.         MakeDevices();
  408.     }
  409.     if (!printOnly) {
  410.         assert(diskInfoPtr->summarySector);
  411.         status = Disk_SectorWrite(partFID, diskInfoPtr->summarySector, 1,
  412.                 (Address)summaryPtr);
  413.         if (status != 0) {
  414.         perror("Summary sector write failed (2)");
  415.         exit(status);
  416.         }
  417.         WriteFileDescBitmap(fdBitmapPtr);
  418.         WriteBitmap(cylBitmapPtr);
  419.     }
  420.     }
  421.  
  422.     fflush(stderr);
  423.     fflush(stdout);
  424.     (void)close(partFID);
  425.     exit(0);
  426. }
  427.  
  428.  
  429. /*
  430.  *----------------------------------------------------------------------
  431.  *
  432.  * SetDomainHeader --
  433.  *
  434.  *    Compute the domain header based on the partition size and
  435.  *    other basic disk parameters.
  436.  *
  437.  * Results:
  438.  *    A return code.
  439.  *
  440.  * Side effects:
  441.  *    Fill in the domain header.
  442.  *
  443.  *----------------------------------------------------------------------
  444.  */
  445. void
  446. SetDomainHeader()
  447. {
  448.     register Fsdm_Geometry *geoPtr;
  449.  
  450.     domainPtr->magic = FSDM_DOMAIN_MAGIC;
  451.     domainPtr->firstCylinder = diskInfoPtr->firstCylinder;
  452.     domainPtr->numCylinders = diskInfoPtr->numCylinders;
  453.     /*
  454.      * The device.serverID from the disk is used during boot to discover
  455.      * the host"s spriteID if reverse arp couldn't find a host ID.  The
  456.      * unit number of disk indicates what partition of the disk this
  457.      * domain header applies to.  For example, both the "a" and "c" partitions
  458.      * typically start at sector zero, but only one is valid.  During boot
  459.      * time the unit number is used to decide which partition should be
  460.      * attached.
  461.      */
  462.     domainPtr->device.serverID = spriteID;
  463.     domainPtr->device.type = -1;
  464.     domainPtr->device.unit = partition;
  465.     domainPtr->device.data = (ClientData)-1;
  466.  
  467.     geoPtr = &domainPtr->geometry;
  468.     SetDiskGeometry(&domainPtr->geometry);
  469.  
  470.     SetDomainParts();
  471. }
  472.  
  473. /*
  474.  *----------------------------------------------------------------------
  475.  *
  476.  * SetDiskGeometry --
  477.  *
  478.  *    This computes the rotational set arrangment depending on the
  479.  *    disk geometry.  The basic rules for this are that filesystem blocks
  480.  *    are skewed on successive tracks, and that the skewing pattern
  481.  *    repeats in either 2 or 4 tracks.  This is specific to the fact that
  482.  *    filesystem blocks are 4Kbytes.  This means that one disk track
  483.  *    contains N/4 filesystem blocks and that one sector per track
  484.  *    is wasted if there are an odd number of sectors per track.
  485.  *
  486.  * Results:
  487.  *    None.
  488.  *
  489.  * Side effects:
  490.  *    Fill in the geometry struct.
  491.  *
  492.  *----------------------------------------------------------------------
  493.  */
  494. void
  495. SetDiskGeometry(geoPtr)
  496.     register Fsdm_Geometry    *geoPtr;    /* Fancy geometry information */
  497. {
  498.     int index;            /* Array index */
  499.     int numBlocks;        /* The number of blocks in a rotational set */
  500.     int tracksPerSet;        /* Total number of tracks in a rotational set */
  501.     int numTracks;        /* The number of tracks in the set so far */
  502.     int extraSectors;        /* The number of leftover sectors in a track */
  503.     int offset;            /* The sector offset within a track */
  504.     int startingOffset;        /* The offset of the first block in a track */
  505.     int offsetIncrement;    /* The skew of the starting offset on each
  506.                  * successive track of the rotational set */
  507.     Boolean overlap;        /* TRUE if filesystem blocks overlap tracks */
  508.  
  509.     geoPtr->numHeads = diskInfoPtr->numHeads;
  510.     geoPtr->sectorsPerTrack = diskInfoPtr->numSectors;
  511.  
  512.     /*
  513.      * Figure out some basic parameters of the rotational set.  The number
  514.      * of tracks in the set is either 2 or 4.  If 2, then the blocks on
  515.      * successive tracks are skewed by 1/2 a filesystem block.  If 4,
  516.      * blocks are skewed by 1/4 block.  A 4 track rotational set is best
  517.      * becasue there are more rotational positions.  If, however, it
  518.      * causes 2 or 3 wasted tracks at the end, or if blocks naturally
  519.      * overlap by 1/2 block, then only 2 tracks per rotational set are
  520.      * used.
  521.      */
  522.     switch(geoPtr->numHeads % 4) {
  523.     case 0:
  524.     case 1: {
  525.         extraSectors = geoPtr->sectorsPerTrack % DISK_SECTORS_PER_BLOCK;
  526.         if (extraSectors < DISK_SECTORS_PER_BLOCK/4) {
  527.         /*
  528.          * Not enough extra sectors to overlap blocks onto the
  529.          * next track.  The blocks will fit evenly on a track,
  530.          * but the blocks on the following tracks will be skewed.
  531.          */
  532.         tracksPerSet = 4;
  533.         overlap = FALSE;
  534.         offsetIncrement = DISK_SECTORS_PER_BLOCK/4;
  535.         } else if (extraSectors < DISK_SECTORS_PER_BLOCK/2) {
  536.         /*
  537.          * Enough to overlap the first 1/4 block onto the next track.
  538.          */
  539.         tracksPerSet = 4;
  540.         overlap = TRUE;
  541.         offsetIncrement = DISK_SECTORS_PER_BLOCK * 3/4;
  542.         } else if (extraSectors < DISK_SECTORS_PER_BLOCK * 3/4) {
  543.         /*
  544.          * Enough to overlap 1/2 block.
  545.          */
  546.         tracksPerSet = 2;
  547.         overlap = TRUE;
  548.         offsetIncrement = DISK_SECTORS_PER_BLOCK/2;
  549.         } else {
  550.         /*
  551.          * Enough to overlap 3/4 block.
  552.          */
  553.         tracksPerSet = 4;
  554.         overlap = TRUE;
  555.         offsetIncrement = DISK_SECTORS_PER_BLOCK/4;
  556.         }
  557.         break;
  558.     }
  559.     case 2:
  560.     case 3: {
  561.         /*
  562.          * Instead of wasting 2 or 3 tracks to have a 4 track rotational
  563.          * set, the rotational set is only 2 tracks long.  Also see if
  564.          * the blocks naturally overlap by 1/2 block.
  565.          */
  566.         tracksPerSet = 2;
  567.         offsetIncrement = DISK_SECTORS_PER_BLOCK/2;
  568.         if ((geoPtr->sectorsPerTrack % DISK_SECTORS_PER_BLOCK) <
  569.               DISK_SECTORS_PER_BLOCK/2) {
  570.         overlap = FALSE;
  571.         } else {
  572.         overlap = TRUE;
  573.         }
  574.     }
  575.     }
  576.     if (!overlapBlocks) {
  577.     overlap = FALSE;
  578.     offsetIncrement = 0;
  579.     }
  580.     printf("overlap %s, offsetIncrement %d\n", (overlap ? "TRUE" : "FALSE"),
  581.               offsetIncrement);
  582.     /*
  583.      * Determine rotational position of the blocks in the rotational set.
  584.      */
  585.     extraSectors = geoPtr->sectorsPerTrack;
  586.     startingOffset = 0;
  587.     offset = startingOffset;
  588.     for (numBlocks = 0, numTracks = 0 ; ; ) {
  589.     if (extraSectors >= DISK_SECTORS_PER_BLOCK) {
  590.         /*
  591.          * Ok to fit in another filesystem block on this track.
  592.          */
  593.         geoPtr->blockOffset[numBlocks] = offset;
  594.         numBlocks++;    
  595.         offset += DISK_SECTORS_PER_BLOCK;
  596.         extraSectors -= DISK_SECTORS_PER_BLOCK;
  597.     } else {
  598.         /*
  599.          * The current block has to take up room on the next track.
  600.          */
  601.         numTracks++;
  602.         if (numTracks < tracksPerSet) {
  603.         /*
  604.          * Ok to go to the next track.
  605.          */
  606.         startingOffset += offsetIncrement;
  607.         if (overlap) {
  608.             /*
  609.              * If the current block can overlap to the next track,
  610.              * use the current offset.  Because of the overlap
  611.              * there are fewer sectors available for blocks on
  612.              * the next track.
  613.              */
  614.             geoPtr->blockOffset[numBlocks] = offset;
  615.             numBlocks++;
  616.             extraSectors = geoPtr->sectorsPerTrack - startingOffset;
  617.         }
  618.         offset = startingOffset + numTracks * geoPtr->sectorsPerTrack;
  619.         if (!overlap) {
  620.             /*
  621.              * If no overlap the whole next track is available.
  622.              */
  623.             extraSectors = geoPtr->sectorsPerTrack;
  624.         }
  625.         } else {
  626.         /*
  627.          * Done.
  628.          */
  629.         for (index = numBlocks; index < FSDM_MAX_ROT_POSITIONS; index++){
  630.             geoPtr->blockOffset[index] = -1;
  631.         }
  632.         break;
  633.         }
  634.     }
  635.     }
  636.     geoPtr->blocksPerRotSet = numBlocks;
  637.     geoPtr->tracksPerRotSet = tracksPerSet;
  638.     geoPtr->rotSetsPerCyl = geoPtr->numHeads / tracksPerSet;
  639.     geoPtr->blocksPerCylinder = numBlocks * geoPtr->rotSetsPerCyl;
  640.  
  641.     /*
  642.      * Now the rotational positions have to be sorted so that rotationally
  643.      * optimal blocks can be found.  The array sortedOffsets is set so
  644.      * that the I'th element has the index into blockOffset which contains
  645.      * the I'th rotational position, eg.
  646.      *    blockOffset    sortedOffsets
  647.      *        0 (+0)        0
  648.      *        8 (+0)        2
  649.      *        4 (+17)        1
  650.      *       12 (+17)        3
  651.      */
  652.  
  653.     offsetIncrement = DISK_SECTORS_PER_BLOCK / tracksPerSet;
  654.     for (index = 0 ; index < FSDM_MAX_ROT_POSITIONS ; index++) {
  655.     geoPtr->sortedOffsets[index] = -1;
  656.     }
  657.     for (index = 0 ; index < numBlocks ; index++) {
  658.     offset = geoPtr->blockOffset[index] % geoPtr->sectorsPerTrack;
  659.     geoPtr->sortedOffsets[offset/offsetIncrement] = index;
  660.     }
  661. }
  662.  
  663. /*
  664.  *----------------------------------------------------------------------
  665.  *
  666.  * SetDomainParts --
  667.  *
  668.  *    Set up the way the domain is divided into 4 areas:  the bitmap
  669.  *    for the file descriptors, the file descriptors, the bitmap for
  670.  *    the data blocks, and the data blocks.
  671.  *
  672.  * Results:
  673.  *    The geometry information is completed.
  674.  *
  675.  * Side effects:
  676.  *    None.
  677.  *
  678.  *----------------------------------------------------------------------
  679.  */
  680. void
  681. SetDomainParts()
  682. {
  683.     register Fsdm_Geometry *geoPtr;
  684.     int            numFiles;
  685.     int         numBlocks;
  686.     int         offset;    
  687.     int         numSectors;
  688.     int            numSets;
  689.     int         bitmapBytes;
  690.  
  691.     /*
  692.      * Set aside a number of blocks at the begining of the partition for
  693.      * things like the super block, the boot program, and the domain header.
  694.      * It is easiest to do this by reserving one or more rotational sets.
  695.      */
  696.     geoPtr = &domainPtr->geometry;
  697.     numSectors = geoPtr->tracksPerRotSet * geoPtr->sectorsPerTrack;
  698.     for ( numSets = 1; ; numSets++ ) {
  699.     if (numSets * numSectors >
  700.         diskInfoPtr->domainSector + diskInfoPtr->numDomainSectors) {
  701.         break;
  702.     }
  703.     }
  704.     printf("Reserving %d blocks for domain header, etc.\n",
  705.             numSets*geoPtr->blocksPerRotSet);
  706.     /*
  707.      * Determine the number of filesystem blocks available and compute a
  708.      * first guess at the number of file descriptors.  If at the end of
  709.      * the computation things don't fit nicely, then the number of files
  710.      * is changed and the computation is repeated.
  711.      */
  712.     numFiles = 0;
  713.     do {
  714.     numBlocks = geoPtr->blocksPerCylinder * diskInfoPtr->numCylinders -
  715.             numSets * geoPtr->blocksPerRotSet;
  716.     if (numFiles == 0) {
  717.         numFiles = numBlocks * DISK_KBYTES_PER_BLOCK / kbytesToFileDesc;
  718.     }
  719.     numFiles          &= ~(FSDM_FILE_DESC_PER_BLOCK-1);
  720.     offset              = numSets * geoPtr->blocksPerRotSet;
  721.  
  722.     domainPtr->fdBitmapOffset = offset;
  723.     bitmapBytes          = (numFiles - 1) / BITS_PER_BYTE + 1;
  724.     domainPtr->fdBitmapBlocks = (bitmapBytes - 1) / FS_BLOCK_SIZE + 1;
  725.     numBlocks          -= domainPtr->fdBitmapBlocks;
  726.     offset              += domainPtr->fdBitmapBlocks;
  727.  
  728.     domainPtr->fileDescOffset = offset;
  729.     domainPtr->numFileDesc      = numFiles;
  730.     numBlocks          -= numFiles / FSDM_FILE_DESC_PER_BLOCK;
  731.     offset              += numFiles / FSDM_FILE_DESC_PER_BLOCK;
  732.     /*
  733.      * The data blocks will start on a cylinder.  Try the next
  734.      * cylinder boundary after the start of the bitmap.
  735.      */
  736.     domainPtr->bitmapOffset      = offset;
  737.     domainPtr->dataOffset      = ((offset-1) / geoPtr->blocksPerCylinder + 1)
  738.                      * geoPtr->blocksPerCylinder;
  739.     domainPtr->dataBlocks      = domainPtr->numCylinders *
  740.                       geoPtr->blocksPerCylinder -
  741.                       domainPtr->dataOffset;
  742.     bitmapBytes          = (domainPtr->dataBlocks * DISK_KBYTES_PER_BLOCK -
  743.                        1) / BITS_PER_BYTE + 1;
  744.     domainPtr->bitmapBlocks      = (bitmapBytes - 1) / FS_BLOCK_SIZE + 1;
  745.     /*
  746.      * Check the size of the bit map against space available for it
  747.      * between the end of the file descriptors and the start of the
  748.      * data blocks.
  749.      */
  750.     if (domainPtr->dataOffset - domainPtr->bitmapOffset <
  751.         domainPtr->bitmapBlocks) {
  752.         int numBlocksNeeded;
  753.         /*
  754.          * Need more blocks to hold the bitmap.  Reduce the number
  755.          * of file descriptors to get the blocks and re-iterate.
  756.          */
  757.         numBlocksNeeded = domainPtr->bitmapBlocks -
  758.         (domainPtr->dataOffset - domainPtr->bitmapOffset);
  759.         numFiles -= numBlocksNeeded * FSDM_FILE_DESC_PER_BLOCK;
  760.     } else if (domainPtr->dataOffset - domainPtr->bitmapOffset >
  761.             domainPtr->bitmapBlocks) {
  762.         int extraBlocks;
  763.         /*
  764.          * There are extra blocks between the end of the file descriptors
  765.          * and the start of the bitmap.  Increase the number of
  766.          * file descriptors and re-iterate.
  767.          */
  768.         extraBlocks = domainPtr->dataOffset - domainPtr->bitmapOffset -
  769.             domainPtr->bitmapBlocks;
  770.         numFiles += extraBlocks * FSDM_FILE_DESC_PER_BLOCK;
  771.     }
  772.     } while (domainPtr->dataOffset - domainPtr->bitmapOffset !=
  773.         domainPtr->bitmapBlocks);
  774.     domainPtr->dataCylinders    = domainPtr->dataBlocks /
  775.                   geoPtr->blocksPerCylinder ;
  776. }
  777.  
  778. /*
  779.  *----------------------------------------------------------------------
  780.  *
  781.  * SetSummaryInfo --
  782.  *
  783.  *    Initialize the summary information for the domain.  It is well
  784.  *    known that this occupies one sector.
  785.  *
  786.  * Results:
  787.  *    A return code.
  788.  *
  789.  * Side effects:
  790.  *    Fill in the summary info.
  791.  *
  792.  *----------------------------------------------------------------------
  793.  */
  794. void
  795. SetSummaryInfo()
  796. {
  797.  
  798.     bzero((Address)summaryPtr, DEV_BYTES_PER_SECTOR);
  799.  
  800.     strcpy(summaryPtr->domainPrefix, "(new domain)");
  801.     /*
  802.      * 4 blocks are already allocated for the root directory.
  803.      */
  804.     summaryPtr->numFreeKbytes = domainPtr->dataBlocks * (FS_BLOCK_SIZE / 1024)
  805.                 - 4;
  806.     /*
  807.      * 3 file descriptors are already used, 0 and 1 are reserved and
  808.      * 2 is for the root.
  809.      */
  810.     summaryPtr->numFreeFileDesc = domainPtr->numFileDesc - 3;
  811.     /*
  812.      * The summary state field is unused.
  813.      */
  814.     summaryPtr->state = 0;
  815.     /*
  816.      * The domain number under which this disk partition is mounted is
  817.      * recorded on disk so servers re-attach disks under the same "name".
  818.      * We set it to the special value so it gets a new number assigned
  819.      * when it is first attached.
  820.      */
  821.     summaryPtr->domainNumber = -1;
  822.     /*
  823.      * The flags field is used to record whether or not the disk has been
  824.      * safely "sync"ed to disk upon shutdown.
  825.      */
  826.     summaryPtr->flags = 0;
  827.     summaryPtr->attachSeconds = 0;
  828.     summaryPtr->detachSeconds = 0;
  829.     summaryPtr->fixCount = 0;
  830. }
  831.  
  832. /*
  833.  *----------------------------------------------------------------------
  834.  *
  835.  * WriteAllFileDescs --
  836.  *
  837.  *    Write out the file descriptor array to disk.
  838.  *
  839.  * Results:
  840.  *    None.
  841.  *
  842.  * Side effects:
  843.  *    None.
  844.  *
  845.  *----------------------------------------------------------------------
  846.  */
  847. void
  848. WriteAllFileDescs()
  849. {
  850.     int                status;
  851.     char            *bitmap;
  852.     char            *block;
  853.     register Fsdm_FileDescriptor    *fileDescPtr;
  854.     register int        index;
  855.  
  856.     bitmap = MakeFileDescBitmap();
  857.     if (!printOnly) {
  858.     status = Disk_BlockWrite(partFID, domainPtr,
  859.                 domainPtr->fdBitmapOffset,
  860.                 domainPtr->fdBitmapBlocks, (Address)bitmap);
  861.     if (status != 0) {
  862.         fprintf(stderr, "WriteAllFileDescs: Could write fd bitmap\n");
  863.         exit(1);
  864.     }
  865.     }
  866.     /*
  867.      * Make the first block of file descriptors.  This contains some
  868.      * canned file descriptors for the root, bad block file, and the
  869.      * lost and found directory.  For (early system) testing an empty file
  870.      * can also be created.
  871.      */
  872.     block = (char *)malloc(FS_BLOCK_SIZE);
  873.     bzero(block, FS_BLOCK_SIZE);
  874.     for (index = 0;
  875.          index < FSDM_FILE_DESC_PER_BLOCK;
  876.      index++ ) {
  877.     fileDescPtr = (Fsdm_FileDescriptor *)((int)block +
  878.                        index * FSDM_MAX_FILE_DESC_SIZE);
  879.     fileDescPtr->magic = FSDM_FD_MAGIC;
  880.     if (index < FSDM_BAD_BLOCK_FILE_NUMBER) {
  881.         fileDescPtr->flags = FSDM_FD_RESERVED;
  882.     } else if (index == FSDM_BAD_BLOCK_FILE_NUMBER) {
  883.         InitDesc(fileDescPtr, FS_FILE, 0, -1, -1, 0, 0, 0700, curTime.tv_sec);
  884.         fileDescPtr->permissions = 0000;
  885.         fileDescPtr->numLinks = 0;
  886.     } else if (index == FSDM_ROOT_FILE_NUMBER) {
  887.         InitDesc(fileDescPtr, FS_DIRECTORY, FS_BLOCK_SIZE, -1, -1, 0,
  888.             0, 0755, curTime.tv_sec);
  889.         /*
  890.          * Place the data in the first file system block.
  891.          */
  892.         fileDescPtr->direct[0] = 0;
  893.     } else {
  894.         fileDescPtr->flags = FSDM_FD_FREE;
  895.     }
  896.     }
  897.     if (!printOnly) {
  898.     /*
  899.      * Write out the first, specially hand crafted, block of file
  900.      * descriptors.
  901.      */
  902.     status = Disk_BlockWrite(partFID, domainPtr, 
  903.                  domainPtr->fileDescOffset,
  904.                  1, (Address)block);
  905.     if (status != 0) {
  906.         fprintf(stderr, "WriteAllFileDescs: Couldn't write descriptor\n");
  907.         exit(1);
  908.     }
  909.     /*
  910.      * Redo the block for the remaining file descriptors
  911.      */
  912.     bzero(block, FS_BLOCK_SIZE);
  913.     for (index = 0;
  914.          index < FSDM_FILE_DESC_PER_BLOCK;
  915.          index++ ) {
  916.         fileDescPtr = (Fsdm_FileDescriptor *)((int)block + index *
  917.                            FSDM_MAX_FILE_DESC_SIZE);
  918.         fileDescPtr->magic = FSDM_FD_MAGIC;
  919.         fileDescPtr->flags = FSDM_FD_FREE;
  920.     }
  921.     /*
  922.      * Write out the remaining file descriptors.
  923.      */
  924.     for (index = FSDM_FILE_DESC_PER_BLOCK;
  925.          index < domainPtr->numFileDesc;
  926.          index += FSDM_FILE_DESC_PER_BLOCK) {
  927.         status = Disk_BlockWrite(partFID, domainPtr,
  928.              domainPtr->fileDescOffset + (index/FSDM_FILE_DESC_PER_BLOCK),
  929.              1, (Address)block);
  930.         if (status != 0) {
  931.         fprintf(stderr, 
  932.             "WriteAllFileDescs: Couldn't write descriptor (2)\n");
  933.         exit(1);
  934.         }
  935.     }
  936.     }
  937. }
  938.  
  939.  
  940. /*
  941.  *----------------------------------------------------------------------
  942.  *
  943.  * MakeFileDescBitmap --
  944.  *
  945.  *    Compute out the bitmap for file descriptor array to disk.
  946.  *
  947.  * Results:
  948.  *    None.
  949.  *
  950.  * Side effects:
  951.  *    None.
  952.  *
  953.  *----------------------------------------------------------------------
  954.  */
  955. char *
  956. MakeFileDescBitmap()
  957. {
  958.     register char    *bitmap;
  959.     register int    index;
  960.  
  961.     /*
  962.      * Allocate and initialize the bitmap to all 0"s to mean all free.
  963.      */
  964.     bitmap = (char *)malloc((unsigned) domainPtr->fdBitmapBlocks *
  965.                  FS_BLOCK_SIZE);
  966.     bzero((Address)bitmap, domainPtr->fdBitmapBlocks * FS_BLOCK_SIZE);
  967.  
  968.     /*
  969.      * Reserve file descriptors 0, 1, and 2.  File number 0 is not used at 
  970.      * all in the filesystem.  File number 1 is for the file with bad blocks.
  971.      * File number 2 (FSDM_ROOT_FILE_NUMBER) is the root directory of the domain.
  972.      *
  973.      * IF THIS CHANGES remember to fix SetSummaryInfo
  974.      */
  975.     bitmap[0] |= 0xe0;
  976.  
  977.     /*
  978.      * Set the bits in the map at the end that don't correspond to
  979.      * any existing file descriptors.
  980.      */
  981.     index = domainPtr->numFileDesc / BITS_PER_BYTE;
  982.     if (domainPtr->numFileDesc % BITS_PER_BYTE) {
  983.     register int bitIndex;
  984.     /*
  985.      * Take care the last byte that only has part of its bits set.
  986.      */
  987.     for (bitIndex = domainPtr->numFileDesc % BITS_PER_BYTE;
  988.          bitIndex < BITS_PER_BYTE;
  989.          bitIndex++) {
  990.         bitmap[index] |= 1 << ((BITS_PER_BYTE - 1) - bitIndex);
  991.     }
  992.     index++;
  993.     }
  994.     for ( ; index < domainPtr->fdBitmapBlocks * FS_BLOCK_SIZE; index++) {
  995.     bitmap[index] = 0xff;
  996.     }
  997.  
  998.     if (printOnly) {
  999.     Disk_PrintFileDescBitmap(domainPtr, bitmap);
  1000.     }
  1001.     return(bitmap);
  1002. }
  1003.  
  1004. /*
  1005.  *----------------------------------------------------------------------
  1006.  *
  1007.  * WriteAndInitDataBitmap --
  1008.  *
  1009.  *    Write out the bitmap for the data blocks.  This knows that the
  1010.  *    first 4K is allocated to the root directory.
  1011.  *
  1012.  * Results:
  1013.  *    A return code from the writes.
  1014.  *
  1015.  * Side effects:
  1016.  *    Write the bitmap.
  1017.  *
  1018.  *----------------------------------------------------------------------
  1019.  */
  1020. void
  1021. WriteAndInitDataBitmap()
  1022. {
  1023.     int        status;
  1024.     char    *bitmap;
  1025.     int        kbytesPerCyl;
  1026.     int        bitmapBytesPerCyl;
  1027.     int        index;
  1028.  
  1029.     bitmap = (char *)malloc((unsigned) domainPtr->bitmapBlocks * FS_BLOCK_SIZE);
  1030.     bzero(bitmap, domainPtr->bitmapBlocks * FS_BLOCK_SIZE);
  1031.     /*
  1032.      * Set the bit corresponding to the 4K used for the root directory.
  1033.      *   ________
  1034.      *    |0______7|    Bits are numbered like this in a byte.
  1035.      *
  1036.      * IF THIS CHANGES remember to fix SetSummaryInfo()
  1037.      */
  1038.     bitmap[0] |= 0xf0;
  1039.     /*
  1040.      * The bitmap is organized by cylinder.  There are whole number of
  1041.      * bytes in the bitmap for each cylinder.  Each bit in the bitmap
  1042.      * corresponds to 1 kbyte on the disk.
  1043.      */
  1044.     kbytesPerCyl = domainPtr->geometry.blocksPerCylinder * DISK_KBYTES_PER_BLOCK;
  1045.     bitmapBytesPerCyl = (kbytesPerCyl - 1) / BITS_PER_BYTE + 1;
  1046.     if ((kbytesPerCyl % BITS_PER_BYTE) != 0) {
  1047.     /*
  1048.      * There are bits in the last byte of the bitmap for each cylinder
  1049.      * that don't have kbytes behind them.  Set those bits here so
  1050.      * the blocks don't get allocated.
  1051.      */
  1052.     register int extraBits;
  1053.     register int mask;
  1054.  
  1055.     extraBits = kbytesPerCyl % BITS_PER_BYTE;
  1056.     /*
  1057.      * Set up a mask that has the right part filled with 1"s.
  1058.      */
  1059.     mask = 0x0;
  1060.     for ( ; extraBits < BITS_PER_BYTE ; extraBits++) {
  1061.         mask |= 1 << ((BITS_PER_BYTE - 1) - extraBits);
  1062.     }
  1063.     for (index = 0;
  1064.          index < domainPtr->dataBlocks * DISK_KBYTES_PER_BLOCK / BITS_PER_BYTE;
  1065.          index += bitmapBytesPerCyl) {
  1066.         bitmap[index + bitmapBytesPerCyl - 1] |= mask;
  1067.     }
  1068.     }
  1069.     /*
  1070.      * Set the bits in the bitmap that correspond to non-existent cylinders;
  1071.      * the bitmap is allocated a whole number of blocks on the disk
  1072.      * so there are bytes at its end that don't have blocks behind them.
  1073.      */
  1074.  
  1075.     for (index = domainPtr->dataCylinders * bitmapBytesPerCyl;
  1076.      index < domainPtr->bitmapBlocks * FS_BLOCK_SIZE;
  1077.      index++) {
  1078.     bitmap[index] = 0xff;
  1079.     }
  1080.     if (printOnly) {
  1081.     Disk_PrintDataBlockBitmap(domainPtr, bitmap);
  1082.     } else {
  1083.     status = Disk_BlockWrite(partFID, domainPtr, 
  1084.                  domainPtr->bitmapOffset,
  1085.                  domainPtr->bitmapBlocks, (Address)bitmap);
  1086.     if (status != 0) {
  1087.         fprintf(stderr, "WriteAndInitDataBitmap: Couldn't write bitmap\n");
  1088.         exit(status);
  1089.     }
  1090.     }
  1091. }
  1092.  
  1093.  
  1094. /*
  1095.  *----------------------------------------------------------------------
  1096.  *
  1097.  * WriteRootDirectory --
  1098.  *
  1099.  *    Write the data blocks of the root directory.
  1100.  *
  1101.  * Results:
  1102.  *    A return code from the writes.
  1103.  *
  1104.  * Side effects:
  1105.  *    Write the root directory"s data block.
  1106.  *
  1107.  *----------------------------------------------------------------------
  1108.  */
  1109. void
  1110. WriteRootDirectory()
  1111. {
  1112.     int        status;
  1113.     char    *block;
  1114.     Fslcl_DirEntry    *dirEntryPtr;
  1115.     int        offset;
  1116.     int        i;
  1117.  
  1118.     block = (char *)malloc(FS_BLOCK_SIZE);
  1119.     CreateDir(block, FSDM_ROOT_FILE_NUMBER, FSDM_ROOT_FILE_NUMBER);
  1120.  
  1121.     if (printOnly) {
  1122.     printf("Root Directory\n");
  1123.     offset = 0;
  1124.     dirEntryPtr = (Fslcl_DirEntry *)block;
  1125.     Disk_PrintDirEntry(dirEntryPtr);
  1126.     offset += dirEntryPtr->recordLength;
  1127.     dirEntryPtr = (Fslcl_DirEntry *)((int)block + offset);
  1128.     Disk_PrintDirEntry(dirEntryPtr);
  1129.     } else {
  1130.     /*
  1131.      * This write trounces the data beyond the stuff allocated to
  1132.      * the root directory.  Currently this is ok and is done because
  1133.      * BlockWrite writes whole numbers of filesystem blocks.
  1134.      */
  1135.     status = Disk_BlockWrite(partFID, domainPtr,
  1136.                  domainPtr->dataOffset, 1, block);
  1137.     if (status != 0) {
  1138.         fprintf(stderr, "WriteRootDirectory: Couldn't write directory\n");
  1139.         exit(status);
  1140.     }
  1141.     }
  1142. }
  1143.  
  1144. /*
  1145.  * The 8 partitions, a through h.
  1146.  */
  1147. #define    A_PART    0
  1148. #define B_PART    1
  1149. #define C_PART    2
  1150. #define D_PART    3
  1151. #define E_PART    4
  1152. #define F_PART    5
  1153. #define G_PART    6
  1154. #define H_PART    7
  1155.  
  1156. #define    BUF_SIZE    100
  1157.  
  1158. char        buf[BUF_SIZE];
  1159. char        fullBuf[BUF_SIZE];
  1160.  
  1161.  
  1162. /*
  1163.  *----------------------------------------------------------------------
  1164.  *
  1165.  * ScanDiskTab --
  1166.  *
  1167.  *    Initialize the disk info struct by looking up this disk type in
  1168.  *    the disk table.
  1169.  *
  1170.  * Results:
  1171.  *    A pointer to a disk info struct.
  1172.  *
  1173.  * Side effects:
  1174.  *    Disk info struct malloc'd and initialized.  The disk header will be
  1175.  *    written if is successfully set up.
  1176.  *
  1177.  *----------------------------------------------------------------------
  1178.  */
  1179. Disk_Info *
  1180. ScanDiskTab()
  1181. {
  1182.     FILE        *fp;
  1183.     int            len;
  1184.     char        *bufPtr;
  1185.     int            fullBufLen;
  1186.     Fsdm_DiskPartition    partTable[FSDM_NUM_DISK_PARTS];
  1187.     int            i;
  1188.     int            sectorsPerTrack;
  1189.     int            tracksPerCylinder;
  1190.     int            sectorsPerCylinder;
  1191.     int            numCylinders;
  1192.     Disk_Info        *diskInfoPtr;
  1193.  
  1194.  
  1195.     fp = fopen("/etc/disktab", "r");
  1196.     if (fp == NULL) {
  1197.     perror("/etc/disktab");
  1198.     exit(1);
  1199.     }
  1200.     len = strlen(diskType);
  1201.     /*
  1202.      * Scan until we reach a line that contains the disk type in it.
  1203.      */
  1204.     while (fgets(buf, BUF_SIZE, fp) != NULL) {
  1205.     if (strncmp(diskType, buf, len) == 0 &&
  1206.         buf[len] == '|') {
  1207.         /*
  1208.          * We found the disk type.
  1209.          */
  1210.         break;
  1211.     }
  1212.     }
  1213.     if (strncmp(diskType, buf, len) != 0) {
  1214.     fprintf(stderr, "`%s' not in disktab\n", diskType);
  1215.     exit(1);
  1216.     }
  1217.  
  1218.     fullBufLen = 0;
  1219.     /*
  1220.      * Now cram all of the lines that end in "\" together.
  1221.      */
  1222.     while (1) {
  1223.     for (bufPtr = buf; *bufPtr != '\n' && *bufPtr != '\\'; bufPtr++) {
  1224.         if (*bufPtr != ' ' && *bufPtr != '\t') {
  1225.         fullBuf[fullBufLen] = *bufPtr;
  1226.         fullBufLen++;
  1227.         }
  1228.     }
  1229.     if (*bufPtr == '\n') {
  1230.         fullBuf[fullBufLen] = 0;
  1231.         break;
  1232.     }
  1233.     if (fgets(buf, BUF_SIZE, fp) == NULL) {
  1234.         fprintf(stderr, "Premature EOF\n");
  1235.         exit(1);
  1236.     }
  1237.     }
  1238.     /*
  1239.      * Now build up a partition table.
  1240.      */
  1241.     for (i = 0; i < FSDM_NUM_DISK_PARTS; i++) {
  1242.     partTable[i].firstCylinder = 0;
  1243.     partTable[i].numCylinders = 0;
  1244.     }
  1245.     for (bufPtr = fullBuf; *bufPtr != 0; bufPtr++) {
  1246.     int    partition;
  1247.  
  1248.     if (strncmp(bufPtr, ":ns#", 4) == 0) {
  1249.         bufPtr += 4;
  1250.         sscanf(bufPtr, "%d", §orsPerTrack);
  1251.     } else if (strncmp(bufPtr, ":nt#", 4) == 0) {
  1252.         bufPtr += 4;
  1253.         sscanf(bufPtr, "%d", &tracksPerCylinder);
  1254.     } else if (strncmp(bufPtr, ":nc#", 4) == 0) {
  1255.         bufPtr += 4;
  1256.         sscanf(bufPtr, "%d", &numCylinders);
  1257.     } else if (strncmp(bufPtr, ":p", 2) == 0) {
  1258.         /*
  1259.          * Skip past the ":p".
  1260.          */
  1261.         bufPtr += 2;
  1262.         partition = *bufPtr - 'a';
  1263.         /*
  1264.          * Skip past the partition character and the #.
  1265.          */
  1266.         bufPtr += 2;
  1267.         sscanf(bufPtr, "%d", &partTable[partition].numCylinders);
  1268.     }
  1269.     }
  1270.     /*
  1271.      * Now that we've built up the number of cylinders build up the
  1272.      * cylinder offsets.
  1273.      */
  1274.     sectorsPerCylinder = sectorsPerTrack * tracksPerCylinder;
  1275.     for (i = 0; i < FSDM_NUM_DISK_PARTS; i++) {
  1276.     partTable[i].numCylinders /= sectorsPerCylinder;
  1277.     }
  1278.  
  1279.     partTable[A_PART].firstCylinder = 0;
  1280.     partTable[B_PART].firstCylinder = partTable[A_PART].numCylinders;
  1281.     partTable[C_PART].firstCylinder = 0;
  1282.     partTable[D_PART].firstCylinder = partTable[B_PART].firstCylinder + 
  1283.             partTable[B_PART].numCylinders;
  1284.     partTable[E_PART].firstCylinder = partTable[D_PART].firstCylinder + 
  1285.             partTable[D_PART].numCylinders;
  1286.     partTable[F_PART].firstCylinder = partTable[E_PART].firstCylinder + 
  1287.             partTable[E_PART].numCylinders;
  1288.     partTable[F_PART].numCylinders = 
  1289.             numCylinders - (partTable[E_PART].firstCylinder +
  1290.                     partTable[E_PART].numCylinders);
  1291.     partTable[G_PART].firstCylinder = partTable[B_PART].firstCylinder + 
  1292.             partTable[B_PART].numCylinders;
  1293.     partTable[G_PART].numCylinders = 
  1294.             numCylinders - (partTable[B_PART].firstCylinder +
  1295.                     partTable[B_PART].numCylinders);
  1296.  
  1297.     /*
  1298.      * Print out the partition table.
  1299.      */
  1300.     printf("Sectors-per-track:    %d\n", sectorsPerTrack);
  1301.     printf("Tracks-per-cylinder:    %d\n", tracksPerCylinder);
  1302.     printf("Sectors-per-cylinder:    %d\n", sectorsPerCylinder);
  1303.     printf("Num-cylinders:        %d\n\n", numCylinders);
  1304.     printf("Partition    First-Cylinder        Num-Cylinders\n");
  1305.     for (i = 0; i < FSDM_NUM_DISK_PARTS; i++) {
  1306.     printf("%c        %d            %d\n",
  1307.            'a' + i, partTable[i].firstCylinder, 
  1308.            partTable[i].numCylinders);
  1309.     }
  1310.  
  1311.     /*
  1312.      * Set up a disk header and write it to sector 0.
  1313.      */
  1314.  
  1315.     if (!printOnly) {
  1316.     int        *headerPtr;
  1317.     Fsdm_DiskHeader    header;
  1318.     int        checkSum;
  1319.     int        status;
  1320.  
  1321.     bzero(&header, sizeof(header));
  1322.     strcpy(header.asciiLabel, diskType);
  1323.     header.magic = FSDM_DISK_MAGIC;
  1324.     header.numCylinders = numCylinders;
  1325.     header.numAltCylinders = 0;
  1326.     header.numHeads = tracksPerCylinder;
  1327.     header.numSectors = sectorsPerTrack;
  1328.     header.bootSector = 1;
  1329.     header.numBootSectors = 15;
  1330.     header.summarySector = 17;
  1331.     header.domainSector = 18;
  1332.     header.numDomainSectors = FSDM_NUM_DOMAIN_SECTORS;
  1333.     header.partition = partition;
  1334.     bcopy(partTable, header.map, sizeof(header.map));
  1335.     /*
  1336.      * Compute the checksum.
  1337.      */
  1338.     header.checkSum = FSDM_DISK_MAGIC;
  1339.     checkSum = 0;
  1340.     for (i = 0, headerPtr = (int *)&header; 
  1341.          i < DEV_BYTES_PER_SECTOR; 
  1342.          i += sizeof(int), headerPtr++) {
  1343.         checkSum ^= *headerPtr;
  1344.     }
  1345.     header.checkSum = checkSum;
  1346.     /*
  1347.      * Recompute the checksum and make sure it matches.
  1348.      */
  1349.     checkSum = 0;
  1350.     for (i = 0, headerPtr = (int *)&header; 
  1351.          i < DEV_BYTES_PER_SECTOR; 
  1352.          i += sizeof(int), headerPtr++) {
  1353.         checkSum ^= *headerPtr;
  1354.     }
  1355.     if (checkSum != FSDM_DISK_MAGIC) {
  1356.         fprintf(stderr, "Bad checksum\n");
  1357.         exit(1);
  1358.     }
  1359.  
  1360.     /*
  1361.      * Write out the disk header.  Unless this is a sun.
  1362.      * On suns the disk label is a special format so the
  1363.      * prom can read it.  So we don't mess with it.
  1364.      */
  1365.  
  1366. #if !defined(sun) && !defined(sun3) && !defined(sun4)
  1367.     status = Disk_SectorWrite(partFID, 0, 1, (Address)&header);
  1368.     if (status != 0) {
  1369.         perror("Couldn't write out the disk header");
  1370.         exit(1);
  1371.     }
  1372. #endif
  1373.  
  1374.     }
  1375.  
  1376.  
  1377.     /*
  1378.      * Allocate, initialize and return the disk info struct.
  1379.      */
  1380.     diskInfoPtr = (Disk_Info *)malloc(sizeof(Disk_Info));
  1381.     (void)strcpy(diskInfoPtr->asciiLabel, diskType);
  1382.     diskInfoPtr->bootSector = 1;
  1383.     diskInfoPtr->numBootSectors = 15;
  1384.     diskInfoPtr->summarySector = 17;
  1385.     diskInfoPtr->domainSector = 18;
  1386.     diskInfoPtr->numDomainSectors = FSDM_NUM_DOMAIN_SECTORS;
  1387.     diskInfoPtr->firstCylinder = partTable[partition].firstCylinder;
  1388.     diskInfoPtr->numCylinders = partTable[partition].numCylinders;
  1389.     diskInfoPtr->numHeads = tracksPerCylinder;
  1390.     diskInfoPtr->numSectors = sectorsPerTrack;
  1391.  
  1392.     return(diskInfoPtr);
  1393. }
  1394.  
  1395.  
  1396. /*
  1397.  *----------------------------------------------------------------------
  1398.  *
  1399.  * ReadFileDescBitmap --
  1400.  *
  1401.  *    Read in the file descriptor bitmap.
  1402.  *
  1403.  * Results:
  1404.  *    A pointer to the file descriptor bit map.
  1405.  *
  1406.  * Side effects:
  1407.  *    Memory allocated for the bit map.
  1408.  *
  1409.  *----------------------------------------------------------------------
  1410.  */
  1411. unsigned char *
  1412. ReadFileDescBitmap()
  1413. {
  1414.     register unsigned char *bitmap;
  1415.  
  1416.     /*
  1417.      * Allocate the bitmap.
  1418.      */
  1419.     bitmap = (unsigned char *)malloc(domainPtr->fdBitmapBlocks * FS_BLOCK_SIZE);
  1420.     if (Disk_BlockRead(partFID, domainPtr, domainPtr->fdBitmapOffset,
  1421.           domainPtr->fdBitmapBlocks, (Address)bitmap) < 0) {
  1422.     fprintf(stderr, "ReadFileDescBitmap: Read failed");
  1423.     exit(1);
  1424.     }
  1425.     return(bitmap);
  1426. }
  1427.  
  1428.  
  1429. /*
  1430.  *----------------------------------------------------------------------
  1431.  *
  1432.  * WriteFileDescBitmap --
  1433.  *
  1434.  *    Write out the file descriptor bitmap.
  1435.  *
  1436.  * Results:
  1437.  *    None.
  1438.  *
  1439.  * Side effects:
  1440.  *    None.
  1441.  *
  1442.  *----------------------------------------------------------------------
  1443.  */
  1444. void
  1445. WriteFileDescBitmap(bitmap)
  1446.     register unsigned char     *bitmap;    /* Bitmap to write. */
  1447. {
  1448.     if (Disk_BlockWrite(partFID, domainPtr, domainPtr->fdBitmapOffset,
  1449.            domainPtr->fdBitmapBlocks, (Address)bitmap) < 0) {
  1450.     fprintf(stderr, "WriteFileDescBitmap: Write failed");
  1451.     exit(1);
  1452.     }
  1453. }
  1454.  
  1455.  
  1456. /*
  1457.  *----------------------------------------------------------------------
  1458.  *
  1459.  * ReadBitmap --
  1460.  *
  1461.  *    Read the bitmap off disk.
  1462.  *
  1463.  * Results:
  1464.  *    A pointer to the bitmap.
  1465.  *
  1466.  * Side effects:
  1467.  *    Memory allocated for the bit map.
  1468.  *
  1469.  *----------------------------------------------------------------------
  1470.  */
  1471. unsigned char *
  1472. ReadBitmap()
  1473. {
  1474.     unsigned char *bitmap;
  1475.  
  1476.     bitmap = (unsigned char *)malloc(domainPtr->bitmapBlocks * FS_BLOCK_SIZE);
  1477.     if (Disk_BlockRead(partFID, domainPtr, domainPtr->bitmapOffset,
  1478.           domainPtr->bitmapBlocks, (Address) bitmap) < 0) {
  1479.     fprintf(stderr, "ReadBitmap: Read failed");
  1480.     exit(1);
  1481.     }
  1482.     return(bitmap);
  1483. }
  1484.  
  1485.  
  1486. /*
  1487.  *----------------------------------------------------------------------
  1488.  *
  1489.  * WriteBitmap --
  1490.  *
  1491.  *    Write the bitmap to disk.
  1492.  *
  1493.  * Results:
  1494.  *    None.
  1495.  *
  1496.  * Side effects:
  1497.  *    None.
  1498.  *
  1499.  *----------------------------------------------------------------------
  1500.  */
  1501. void
  1502. WriteBitmap(bitmap)
  1503.     unsigned char        *bitmap;    /* Bitmap to write. */
  1504. {
  1505.     if (Disk_BlockWrite(partFID, domainPtr, domainPtr->bitmapOffset,
  1506.            domainPtr->bitmapBlocks, (Address) bitmap) < 0) {
  1507.     fprintf(stderr, "WriteBitmap: Write failed");
  1508.     exit(1);
  1509.     }
  1510. }
  1511.  
  1512.  
  1513. /*
  1514.  *----------------------------------------------------------------------
  1515.  *
  1516.  * ReadFileDesc --
  1517.  *
  1518.  *    Return the given file descriptor.
  1519.  *
  1520.  * Results:
  1521.  *    None.
  1522.  *
  1523.  * Side effects:
  1524.  *    The file descriptor struct is filled in.
  1525.  *
  1526.  *----------------------------------------------------------------------
  1527.  */
  1528. void
  1529. ReadFileDesc(fdNum, fdPtr)
  1530.     int            fdNum;
  1531.     Fsdm_FileDescriptor    *fdPtr;
  1532. {
  1533.     static char        block[FS_BLOCK_SIZE];
  1534.     int            blockNum;
  1535.     int            offset;
  1536.  
  1537.     blockNum = domainPtr->fileDescOffset + fdNum / FSDM_FILE_DESC_PER_BLOCK;
  1538.     offset = (fdNum & (FSDM_FILE_DESC_PER_BLOCK - 1)) * FSDM_MAX_FILE_DESC_SIZE;
  1539.     if (Disk_BlockRead(partFID, domainPtr, blockNum, 1, 
  1540.                (Address) block) < 0) {
  1541.     fprintf(stderr, "ReadFileDesc: Read failed\n");
  1542.     exit(1);
  1543.     }
  1544.     bcopy((Address)&block[offset], (Address)fdPtr, sizeof(Fsdm_FileDescriptor));
  1545. }
  1546.  
  1547.  
  1548. /*
  1549.  *----------------------------------------------------------------------
  1550.  *
  1551.  * WriteFileDesc --
  1552.  *
  1553.  *    Return the given file descriptor.
  1554.  *
  1555.  * Results:
  1556.  *    None.
  1557.  *
  1558.  * Side effects:
  1559.  *    The file descriptor struct is filled in.
  1560.  *
  1561.  *----------------------------------------------------------------------
  1562.  */
  1563. void
  1564. WriteFileDesc(fdNum, fdPtr)
  1565.     int            fdNum;
  1566.     Fsdm_FileDescriptor    *fdPtr;
  1567. {
  1568.     static char        block[FS_BLOCK_SIZE];
  1569.     int            blockNum;
  1570.     int            offset;
  1571.  
  1572.     blockNum = domainPtr->fileDescOffset + fdNum / FSDM_FILE_DESC_PER_BLOCK;
  1573.     offset = (fdNum & (FSDM_FILE_DESC_PER_BLOCK - 1)) * FSDM_MAX_FILE_DESC_SIZE;
  1574.     if (Disk_BlockRead(partFID, domainPtr, blockNum, 1, 
  1575.                (Address) block) < 0) {
  1576.     fprintf(stderr, "WriteFileDesc: Read failed\n");
  1577.     exit(1);
  1578.     }
  1579.     bcopy(fdPtr, (Address)&block[offset], sizeof(Fsdm_FileDescriptor));
  1580.     if (Disk_BlockWrite(partFID, domainPtr, blockNum, 1, 
  1581.                (Address) block) < 0) {
  1582.     fprintf(stderr, "WriteFileDesc: Write failed\n");
  1583.     exit(1);
  1584.     }
  1585. }
  1586.  
  1587. char    fileBlock[FS_BLOCK_SIZE];
  1588. char    indirectBlock[FS_BLOCK_SIZE];
  1589. int    *indIndexPtr = (int *)indirectBlock;
  1590.  
  1591.  
  1592. /*
  1593.  *----------------------------------------------------------------------
  1594.  *
  1595.  * CopyTree --
  1596.  *
  1597.  *    Copy the tree of files in the given directory
  1598.  *    the disk table.
  1599.  *
  1600.  * Results:
  1601.  *    A pointer to a disk info struct.
  1602.  *
  1603.  * Side effects:
  1604.  *    Disk info struct malloc'd and initialized.  The disk header will be
  1605.  *    written if is successfully set up.
  1606.  *
  1607.  *----------------------------------------------------------------------
  1608.  */
  1609. void
  1610. CopyTree(dirName, dirFDNum, dirFDPtr, parentFDNum, createDir, path)
  1611.     char        *dirName;    /* Name of directory to copy. */
  1612.     int            dirFDNum;    /* File number of directory. */
  1613.     Fsdm_FileDescriptor    *dirFDPtr;    /* File descriptor of directory. */
  1614.     int            parentFDNum;    /* File number of parent. */
  1615.     Boolean        createDir;    /* Should create the directory. */
  1616.     char        *path;
  1617. {
  1618.     DIR            *unixDirPtr;
  1619.     Fslcl_DirEntry        *unixDirEntPtr;
  1620.     DirIndexInfo    indexInfo;
  1621.     Fslcl_DirEntry        *spriteDirEntPtr;
  1622.     char        fileName[FS_MAX_NAME_LENGTH + 1];
  1623.     int            newFDNum;
  1624.     Fsdm_FileDescriptor    newFD;
  1625.     Fsdm_FileDescriptor    *newFDPtr;
  1626.     struct    stat    statBuf;
  1627.     int            followLinks;
  1628.     char        pathName[1024];
  1629.  
  1630.     /*
  1631.      * Get our absolute path name so we can get back if we follow a
  1632.      * symbolic link.
  1633.      */
  1634.     getwd(pathName);
  1635.  
  1636.     if (chdir(dirName) < 0) {
  1637.     perror(dirName);
  1638.     exit(1);
  1639.     }
  1640.  
  1641.     /*
  1642.      * Get a pointer to the UNIX directory.
  1643.      */
  1644.     unixDirPtr = opendir(".");
  1645.     if (unixDirPtr == NULL) {
  1646.     fprintf(stderr, "Can't open directory %s\n", dirName);
  1647.     exit(1);
  1648.     }
  1649.     /*
  1650.      * Open the Sprite directory.
  1651.      */
  1652.     spriteDirEntPtr = OpenDir(dirFDPtr, &indexInfo);
  1653.     if (spriteDirEntPtr == (Fslcl_DirEntry *)NULL) {
  1654.     if (chdir(pathName) < 0) {
  1655.         perror(pathName);
  1656.         exit(1);
  1657.     }
  1658.     }
  1659.     /*
  1660.      * See if there is a "follow.links" file in this directory.  If so
  1661.      * we are supposed to follow symbolic links rather than just copying
  1662.      * the links.
  1663.      */
  1664.     if (stat("follow.links", &statBuf) < 0) {
  1665.     followLinks = 0;
  1666.     } else {
  1667.     printf("Following links ...\n");
  1668.     followLinks = 1;
  1669.     }
  1670.     if (createDir) {
  1671.     CreateDir(indexInfo.dirBlock, dirFDNum, parentFDNum);
  1672.     }
  1673.  
  1674.     for (unixDirEntPtr = (Fslcl_DirEntry *)readdir(unixDirPtr);
  1675.        unixDirEntPtr != NULL;
  1676.        unixDirEntPtr = (Fslcl_DirEntry *)readdir(unixDirPtr)) {
  1677.  
  1678.     if (unixDirEntPtr->nameLength == 1 && 
  1679.         strncmp(unixDirEntPtr->fileName, ".", 1) == 0) {
  1680.         continue;
  1681.     }
  1682.     if (unixDirEntPtr->nameLength == 2 && 
  1683.         strncmp(unixDirEntPtr->fileName, "..", 2) == 0) {
  1684.         continue;
  1685.     }
  1686.     strncpy(fileName, unixDirEntPtr->fileName, unixDirEntPtr->nameLength);
  1687.     fileName[unixDirEntPtr->nameLength] = 0;
  1688.     if (followLinks) {
  1689.         if (stat(fileName, &statBuf) < 0) {
  1690.         perror(fileName);
  1691.         exit(1);
  1692.         }
  1693.     } else {
  1694.         if (lstat(fileName, &statBuf) < 0) {
  1695.         perror(fileName);
  1696.         exit(1);
  1697.         }
  1698.     }
  1699.  
  1700.     newFDNum = freeFDNum;
  1701.     freeFDNum++;
  1702.     MarkFDBitmap(newFDNum, fdBitmapPtr);
  1703.     summaryPtr->numFreeFileDesc--;
  1704.     /*
  1705.      * Read out the file descriptor being careful to save it around
  1706.      * if we found the /dev descriptor.
  1707.      */
  1708.     if ((strcmp(fileName, "dev") == 0) &&
  1709.         (dirFDNum == FSDM_ROOT_FILE_NUMBER)) {
  1710.         if (!(statBuf.st_mode & S_GFDIR)) {
  1711.         fprintf(stderr, "dev isn't a directory\n");
  1712.         exit(1);
  1713.         }
  1714.         ReadFileDesc(newFDNum, &devFD);
  1715.         newFDPtr = &devFD;
  1716.         devFDNum = newFDNum;
  1717.         devFDPtr = newFDPtr;
  1718.     } else {
  1719.         ReadFileDesc(newFDNum, &newFD);
  1720.         newFDPtr = &newFD;
  1721.     }
  1722.     spriteDirEntPtr = AddToDirectory(&indexInfo, spriteDirEntPtr,
  1723.                      newFDNum, fileName);
  1724.     if (statBuf.st_mode & S_GFDIR) {
  1725.         char    newPath[FS_MAX_NAME_LENGTH];
  1726.  
  1727.         /*
  1728.          * Increment the current directories link count because once
  1729.          * the child gets created it will point to the parent.
  1730.          */
  1731.         dirFDPtr->numLinks++;
  1732.         /*
  1733.          * Allocate the currently free file descriptor to this directory.
  1734.          */
  1735.         InitDesc(newFDPtr, FS_DIRECTORY, FS_BLOCK_SIZE, -1, -1, 
  1736.              0, 0, statBuf.st_mode & 07777, statBuf.st_mtime);
  1737.         /*
  1738.          * Give the directory one full block.  The directory will
  1739.          * be initialized by CopyTree when we call it recursively.
  1740.          */
  1741.         newFDPtr->direct[0] = freeBlockNum * FS_FRAGMENTS_PER_BLOCK;
  1742.         MarkDataBitmap(domainPtr, cylBitmapPtr, freeBlockNum,
  1743.                FS_FRAGMENTS_PER_BLOCK);
  1744.         freeBlockNum++;
  1745.         sprintf(newPath, "%s%s/", path, fileName);
  1746.         printf("Directory: %s\n", newPath);
  1747.         CopyTree(fileName, newFDNum, newFDPtr, dirFDNum, TRUE, newPath);
  1748.     } else if ((statBuf.st_mode & S_GFMT) == S_GFREG ||
  1749.            (statBuf.st_mode & S_GFMT) == S_GFLNK) {
  1750.         int    fd;
  1751.         int    blockNum;
  1752.         int    toRead;
  1753.         int    len;
  1754.  
  1755.         blockNum = 0;
  1756.         if ((statBuf.st_mode & S_GFMT) == S_GFREG) {
  1757.         printf("File: %s%s\n", path, fileName);
  1758.         InitDesc(newFDPtr, FS_FILE, statBuf.st_size, -1, -1,
  1759.              0, 0, statBuf.st_mode & 07777, statBuf.st_mtime);
  1760.         /*
  1761.          * Copy the file over.
  1762.          */
  1763.         fd = open(fileName, 0);
  1764.         if (fd < 0) {
  1765.             perror(fileName);
  1766.             exit(1);
  1767.         }
  1768.         len = read(fd, fileBlock, FS_BLOCK_SIZE);
  1769.         if (len < 0) {
  1770.             perror(fileName);
  1771.             exit(1);
  1772.         }
  1773.         toRead = statBuf.st_size;
  1774.         } else {
  1775.         len = readlink(fileName, fileBlock, FS_BLOCK_SIZE);
  1776.         if (len < 0) {
  1777.             perror(fileName);
  1778.             exit(1);
  1779.         }
  1780.         fileBlock[len] = '\0';
  1781.         InitDesc(newFDPtr, FS_SYMBOLIC_LINK, len + 1, -1, -1, 
  1782.              0, 0, 0777, statBuf.st_mtime);
  1783.         printf("Symbolic link: %s%s -> %s\n", 
  1784.             path, fileName, fileBlock);
  1785.         toRead = len + 1;
  1786.         }
  1787.  
  1788.         while (len > 0) {
  1789.         if (blockNum == FSDM_NUM_DIRECT_BLOCKS) {
  1790.             int    i;
  1791.             int    *intPtr;
  1792.             /*
  1793.              * Must allocate an indirect block.
  1794.              */
  1795.             newFDPtr->indirect[0] =
  1796.             VirtToPhys(freeBlockNum * FS_FRAGMENTS_PER_BLOCK);
  1797.             MarkDataBitmap(domainPtr, cylBitmapPtr, freeBlockNum,
  1798.                    FS_FRAGMENTS_PER_BLOCK);
  1799.             freeBlockNum++;
  1800.             summaryPtr->numFreeKbytes -= FS_FRAGMENTS_PER_BLOCK;
  1801.             for (i = 0, intPtr = (int *)indirectBlock; 
  1802.              i < FS_BLOCK_SIZE / sizeof(int); 
  1803.              i++, intPtr++) {
  1804.              *intPtr = FSDM_NIL_INDEX;
  1805.             }
  1806.         }
  1807.         if (blockNum >= FSDM_NUM_DIRECT_BLOCKS) {
  1808.             indIndexPtr[blockNum - FSDM_NUM_DIRECT_BLOCKS] = 
  1809.                     freeBlockNum * FS_FRAGMENTS_PER_BLOCK;
  1810.             MarkDataBitmap(domainPtr, cylBitmapPtr, freeBlockNum,
  1811.                    FS_FRAGMENTS_PER_BLOCK);
  1812.             summaryPtr->numFreeKbytes -= FS_FRAGMENTS_PER_BLOCK;
  1813.         } else {
  1814.             newFDPtr->direct[blockNum] = 
  1815.                     freeBlockNum * FS_FRAGMENTS_PER_BLOCK;
  1816.             if (toRead > FS_BLOCK_SIZE) {
  1817.             MarkDataBitmap(domainPtr, cylBitmapPtr, freeBlockNum,
  1818.                        FS_FRAGMENTS_PER_BLOCK);
  1819.             summaryPtr->numFreeKbytes -= FS_FRAGMENTS_PER_BLOCK;
  1820.             } else {
  1821.             MarkDataBitmap(domainPtr, cylBitmapPtr, freeBlockNum,
  1822.                        (toRead - 1) / FS_FRAGMENT_SIZE + 1);
  1823.             summaryPtr->numFreeKbytes -= 
  1824.                     (toRead - 1) / FS_FRAGMENT_SIZE + 1;
  1825.             }
  1826.         }
  1827.         /*
  1828.          * Write the block out to disk.
  1829.          */
  1830.         if (Disk_BlockWrite(partFID, domainPtr, 
  1831.                     domainPtr->dataOffset + freeBlockNum,
  1832.                     1, (Address)fileBlock) != 0) {
  1833.             fprintf(stderr, "Couldn't write file block\n");
  1834.             exit(1);
  1835.         }
  1836.         blockNum++;
  1837.         freeBlockNum++;
  1838.         if ((statBuf.st_mode & S_GFMT) == S_GFLNK) {
  1839.             break;
  1840.         }
  1841.         toRead -= len;
  1842.         len = read(fd, fileBlock, FS_BLOCK_SIZE);
  1843.         if (len < 0) {
  1844.             perror(fileName);
  1845.             exit(1);
  1846.         }
  1847.         }
  1848.         if (newFDPtr->indirect[0] != FSDM_NIL_INDEX) {
  1849.         if (Disk_BlockWrite(partFID, domainPtr,
  1850.                 newFDPtr->indirect[0] / FS_FRAGMENTS_PER_BLOCK,
  1851.                 1, (Address)indirectBlock) != 0) {
  1852.             fprintf(stderr, "Couldn't write indirect block\n");
  1853.             exit(1);
  1854.         }
  1855.         }
  1856.         close(fd);
  1857.     } else {
  1858.         fprintf(stderr, "Non file or directory\n");
  1859.         exit(1);
  1860.     }
  1861.     WriteFileDesc(newFDNum, newFDPtr);
  1862.  
  1863.     if (spriteDirEntPtr == (Fslcl_DirEntry *)NULL) {
  1864.         fprintf(stderr, "%s is full\n", dirName);
  1865.         break;
  1866.     }
  1867.     }
  1868.  
  1869.     CloseDir(&indexInfo);
  1870.  
  1871.     if (chdir(pathName) < 0) {
  1872.     perror(pathName);
  1873.     exit(1);
  1874.     }
  1875.     closedir(unixDirPtr);
  1876.     return;
  1877. }
  1878.  
  1879.  
  1880. /*
  1881.  *----------------------------------------------------------------------
  1882.  *
  1883.  * OpenDir --
  1884.  *
  1885.  *    Set up the structure to allow moving through the given directory.
  1886.  *
  1887.  * Results:
  1888.  *    None.
  1889.  *
  1890.  * Side effects:
  1891.  *    The index structure is set up and *dirEntryPtrPtr set to point to
  1892.  *    the first directory entry.
  1893.  *
  1894.  *----------------------------------------------------------------------
  1895.  */
  1896. static Fslcl_DirEntry *
  1897. OpenDir(fdPtr, indexInfoPtr)
  1898.     Fsdm_FileDescriptor    *fdPtr;        /* The file descriptor for the
  1899.                      * directory. */
  1900.     DirIndexInfo     *indexInfoPtr;    /* Index info struct */
  1901. {
  1902.     int            fragsToRead;
  1903.  
  1904.     if (fdPtr->lastByte == -1) {
  1905.     /*
  1906.      * Empty directory.
  1907.      */
  1908.     return((Fslcl_DirEntry *) NULL);
  1909.     } else if ((fdPtr->lastByte + 1) % FSLCL_DIR_BLOCK_SIZE != 0) {
  1910.     fprintf(stderr, "Directory not multiple of directory block size.\n");
  1911.     exit(1);
  1912.     } else if (fdPtr->fileType != FS_DIRECTORY) {
  1913.     fprintf(stderr, "OpenDir: Not a directory\n");
  1914.     return((Fslcl_DirEntry *)NULL);
  1915.     }
  1916.  
  1917.     /*
  1918.      * Initialize the index structure.
  1919.      */
  1920.     indexInfoPtr->fdPtr = fdPtr;
  1921.     indexInfoPtr->blockNum = 0;
  1922.     indexInfoPtr->blockAddr = fdPtr->direct[0] / FS_FRAGMENTS_PER_BLOCK + 
  1923.                   domainPtr->dataOffset;
  1924.     /*
  1925.      * Read in the directory block.
  1926.      */
  1927.     if (fdPtr->lastByte != FS_BLOCK_SIZE - 1) {
  1928.     fprintf(stderr, "We created a directory that's not 4K?\n");
  1929.     exit(1);
  1930.     }
  1931.     if (Disk_BlockRead(partFID, domainPtr,
  1932.                indexInfoPtr->blockAddr,
  1933.                1, indexInfoPtr->dirBlock) < 0) {
  1934.     fprintf(stderr, "OpenDir: Read failed block %d\n",
  1935.             indexInfoPtr->blockAddr);
  1936.     exit(1);
  1937.     } 
  1938.     indexInfoPtr->dirOffset = 0;
  1939.     return((Fslcl_DirEntry *) indexInfoPtr->dirBlock);
  1940. }
  1941.  
  1942.  
  1943. /*
  1944.  *----------------------------------------------------------------------
  1945.  *
  1946.  * NextDirEntry --
  1947.  *
  1948.  *    Return a pointer to the next directory entry.
  1949.  *
  1950.  * Results:
  1951.  *    None.
  1952.  *
  1953.  * Side effects:
  1954.  *    The index structure is modified and *dirEntryPtrPtr set to point
  1955.  *    to the next directory entry.
  1956.  *
  1957.  *----------------------------------------------------------------------
  1958.  */
  1959. Fslcl_DirEntry *
  1960. NextDirEntry(indexInfoPtr, dirEntryPtr)
  1961.     DirIndexInfo     *indexInfoPtr;
  1962.     Fslcl_DirEntry        *dirEntryPtr;
  1963. {
  1964.     indexInfoPtr->dirOffset += dirEntryPtr->recordLength;
  1965.     if (indexInfoPtr->dirOffset < FS_BLOCK_SIZE) {
  1966.     /*
  1967.      * The next directory entry is in the current block.
  1968.      */
  1969.     return((Fslcl_DirEntry *)
  1970.             &(indexInfoPtr->dirBlock[indexInfoPtr->dirOffset]));
  1971.     } else {
  1972.     Fsdm_FileDescriptor    *fdPtr;
  1973.     int            i;
  1974.  
  1975.     printf("Adding new block to directory ...\n");
  1976.  
  1977.     /*
  1978.      * Write out the current block and set up the next one.
  1979.      */
  1980.     if (!printOnly) {
  1981.         if (Disk_BlockWrite(partFID, domainPtr, indexInfoPtr->blockAddr,
  1982.                 1, indexInfoPtr->dirBlock) < 0) {
  1983.         fprintf(stderr, "NextDirEntry: Write failed block %d\n",
  1984.                 indexInfoPtr->blockAddr);
  1985.         exit(1);
  1986.         }
  1987.     }
  1988.     fdPtr = indexInfoPtr->fdPtr;
  1989.     fdPtr->lastByte += FS_BLOCK_SIZE;
  1990.     fdPtr->numKbytes += FS_FRAGMENTS_PER_BLOCK;
  1991.     indexInfoPtr->blockNum++;
  1992.     fdPtr->direct[indexInfoPtr->blockNum] = 
  1993.                 freeBlockNum * FS_FRAGMENTS_PER_BLOCK;
  1994.     MarkDataBitmap(domainPtr, cylBitmapPtr, freeBlockNum,
  1995.                FS_FRAGMENTS_PER_BLOCK);
  1996.     indexInfoPtr->blockAddr = freeBlockNum + domainPtr->dataOffset;
  1997.     freeBlockNum++;
  1998.     for (i = 0, dirEntryPtr = (Fslcl_DirEntry *)indexInfoPtr->dirBlock; 
  1999.          i < FS_BLOCK_SIZE / FSLCL_DIR_BLOCK_SIZE;
  2000.      i++,dirEntryPtr=(Fslcl_DirEntry *)((unsigned)dirEntryPtr+FSLCL_DIR_BLOCK_SIZE)) {
  2001.         dirEntryPtr->fileNumber = 0;
  2002.         dirEntryPtr->recordLength = FSLCL_DIR_BLOCK_SIZE;
  2003.         dirEntryPtr->nameLength = 0;
  2004.     }
  2005.     indexInfoPtr->dirOffset = 0;
  2006.     return((Fslcl_DirEntry *) indexInfoPtr->dirBlock);
  2007.     }
  2008. }
  2009.  
  2010.  
  2011. /*
  2012.  *----------------------------------------------------------------------
  2013.  *
  2014.  * CloseDir --
  2015.  *
  2016.  *    Flushes the current directory block to disk, if necessary.
  2017.  *
  2018.  * Results:
  2019.  *    None.
  2020.  *
  2021.  * Side effects:
  2022.  *    The index structure is modified and *dirEntryPtrPtr set to point
  2023.  *    to the next directory entry.
  2024.  *
  2025.  *----------------------------------------------------------------------
  2026.  */
  2027. static void
  2028. CloseDir(indexInfoPtr)
  2029.     DirIndexInfo     *indexInfoPtr;
  2030. {
  2031.  
  2032.     if (!printOnly) {
  2033.     if (Disk_BlockWrite(partFID, domainPtr, indexInfoPtr->blockAddr,
  2034.                 1, indexInfoPtr->dirBlock) < 0) {
  2035.         fprintf(stderr, "CloseDir: Write (2) failed block %d\n",
  2036.                 indexInfoPtr->blockAddr);
  2037.         exit(1);
  2038.     }
  2039.     }
  2040. }
  2041.  
  2042.  
  2043. /*
  2044.  *----------------------------------------------------------------------
  2045.  *
  2046.  * InitDesc --
  2047.  *
  2048.  *    Set up a file descriptor as allocated.
  2049.  *
  2050.  * Results:
  2051.  *    None.
  2052.  *
  2053.  * Side effects:
  2054.  *    File descriptor fields filled in.
  2055.  *
  2056.  *----------------------------------------------------------------------
  2057.  */
  2058. void
  2059. InitDesc(fileDescPtr, fileType, numBytes, devType, devUnit, uid,
  2060.     gid, permissions, time)
  2061.     Fsdm_FileDescriptor    *fileDescPtr;
  2062.     int            fileType;
  2063.     int            numBytes;
  2064.     int            devType;
  2065.     int            devUnit;
  2066.     int            uid;
  2067.     int            gid;
  2068.     int            permissions;
  2069.     int            time;
  2070. {
  2071.     int        index;
  2072.  
  2073.     fileDescPtr->flags = FSDM_FD_ALLOC;
  2074.     fileDescPtr->fileType = fileType;
  2075.     fileDescPtr->permissions = permissions;
  2076.     fileDescPtr->uid = uid;
  2077.     fileDescPtr->gid = gid;
  2078.     fileDescPtr->lastByte = numBytes - 1;
  2079.     fileDescPtr->firstByte = -1;
  2080.     if (fileType == FS_DIRECTORY) {
  2081.     fileDescPtr->numLinks = 2;
  2082.     } else {
  2083.     fileDescPtr->numLinks = 1;
  2084.     }
  2085.     /*
  2086.      * Can't know device information because that depends on
  2087.      * the way the system is configured.
  2088.      */
  2089.     fileDescPtr->devServerID = -1;
  2090.     fileDescPtr->devType = devType;
  2091.     fileDescPtr->devUnit = devUnit;
  2092.  
  2093.     /*
  2094.      * Set the time stamps.  This assumes that universal time,
  2095.      * not local time, is used for time stamps.
  2096.      */
  2097.     fileDescPtr->createTime = time;
  2098.     fileDescPtr->accessTime = 0;
  2099.     fileDescPtr->descModifyTime = time;
  2100.     fileDescPtr->dataModifyTime = time;
  2101.  
  2102.     /*
  2103.      * Place the data in the first filesystem block.
  2104.      */
  2105.     for (index = 0; index < FSDM_NUM_DIRECT_BLOCKS ; index++) {
  2106.     fileDescPtr->direct[index] = FSDM_NIL_INDEX;
  2107.     }
  2108.     for (index = 0; index < FSDM_NUM_INDIRECT_BLOCKS ; index++) {
  2109.     fileDescPtr->indirect[index] = FSDM_NIL_INDEX;
  2110.     }
  2111.     if (numBytes > 0) {
  2112.     int    numBlocks;
  2113.  
  2114.     numBlocks = (numBytes - 1) / FS_BLOCK_SIZE + 1;
  2115.     if (numBlocks > FSDM_NUM_DIRECT_BLOCKS) {
  2116.         fileDescPtr->numKbytes = (numBlocks + 1) * (FS_BLOCK_SIZE / 1024);
  2117.     } else {
  2118.         fileDescPtr->numKbytes = (numBytes + 1023) / 1024;
  2119.     }
  2120.     } else {
  2121.     fileDescPtr->numKbytes = 0;
  2122.     }
  2123.  
  2124.     fileDescPtr->version = 1;
  2125. }
  2126.  
  2127. int fragMasks[FS_FRAGMENTS_PER_BLOCK + 1] = {0x0, 0x08, 0x0c, 0x0e, 0x0f};
  2128.  
  2129.  
  2130. /*
  2131.  *----------------------------------------------------------------------
  2132.  *
  2133.  * MarkDataBitmap --
  2134.  *
  2135.  *    Mark the appropriate bits in the data block bitmap.
  2136.  *
  2137.  * Results:
  2138.  *    None.
  2139.  *
  2140.  * Side effects:
  2141.  *    Data block marked.
  2142.  *
  2143.  *----------------------------------------------------------------------
  2144.  */
  2145. void
  2146. MarkDataBitmap(domainPtr, cylBitmapPtr, blockNum, numFrags)
  2147.     Fsdm_DomainHeader    *domainPtr;
  2148.     unsigned char    *cylBitmapPtr;
  2149.     int            blockNum;
  2150.     int            numFrags;
  2151. {
  2152.     unsigned char    *bitmapPtr;
  2153.  
  2154.     bitmapPtr = GetBitmapPtr(domainPtr, cylBitmapPtr, blockNum);
  2155.     if ((blockNum % domainPtr->geometry.blocksPerCylinder) & 0x1) {
  2156.     *bitmapPtr |= fragMasks[numFrags];
  2157.     } else {
  2158.     *bitmapPtr |= fragMasks[numFrags] << 4;
  2159.     }
  2160. }
  2161.  
  2162.  
  2163.  
  2164. /*
  2165.  *----------------------------------------------------------------------
  2166.  *
  2167.  * CreateDir --
  2168.  *
  2169.  *    Create a directory out of a single file system block.
  2170.  *
  2171.  * Results:
  2172.  *    None.
  2173.  *
  2174.  * Side effects:
  2175.  *    File system block set up as a directory.
  2176.  *
  2177.  *----------------------------------------------------------------------
  2178.  */
  2179. void
  2180. CreateDir(block, dot, dotDot)
  2181.     Address    block;        /* Block to create directory in. */
  2182.     int        dot;        /* File number of directory. */
  2183.     int        dotDot;        /* File number of parent. */
  2184. {
  2185.     Fslcl_DirEntry    *dirEntryPtr;
  2186.     char    *fileName;
  2187.     int        offset;
  2188.     int        length;
  2189.     int        i;
  2190.  
  2191.     dirEntryPtr = (Fslcl_DirEntry *)block;
  2192.     fileName = ".";
  2193.     length = strlen(fileName);
  2194.     dirEntryPtr->fileNumber = dot;
  2195.     dirEntryPtr->recordLength = Fslcl_DirRecLength(length);
  2196.     dirEntryPtr->nameLength = length;
  2197.     strcpy(dirEntryPtr->fileName, fileName);
  2198.     offset = dirEntryPtr->recordLength;
  2199.  
  2200.     dirEntryPtr = (Fslcl_DirEntry *)((int)block + offset);
  2201.     fileName = "..";
  2202.     length = strlen(fileName);
  2203.     dirEntryPtr->fileNumber = dotDot;
  2204.     dirEntryPtr->recordLength = FSLCL_DIR_BLOCK_SIZE - offset;
  2205.     dirEntryPtr->nameLength = length;
  2206.     strcpy(dirEntryPtr->fileName, fileName);
  2207.     /*
  2208.      * Fill out the rest of the directory with empty blocks.
  2209.      */
  2210.     for (dirEntryPtr = (Fslcl_DirEntry *)&block[FSLCL_DIR_BLOCK_SIZE], i = 1; 
  2211.      i < FS_BLOCK_SIZE / FSLCL_DIR_BLOCK_SIZE;
  2212.      i++,dirEntryPtr=(Fslcl_DirEntry *)((int)dirEntryPtr + FSLCL_DIR_BLOCK_SIZE)) {
  2213.      dirEntryPtr->fileNumber = 0;
  2214.      dirEntryPtr->recordLength = FSLCL_DIR_BLOCK_SIZE;
  2215.      dirEntryPtr->nameLength = 0;
  2216.     }
  2217. }
  2218.  
  2219.  
  2220. /*
  2221.  *----------------------------------------------------------------------
  2222.  *
  2223.  * AddToDirectory --
  2224.  *
  2225.  *    Add the file descriptor to a directory.  
  2226.  *
  2227.  * Results:
  2228.  *    None.
  2229.  *
  2230.  * Side effects:
  2231.  *    The directory is modified to contain the orphaned file.
  2232.  *
  2233.  *----------------------------------------------------------------------
  2234.  */
  2235. Fslcl_DirEntry *
  2236. AddToDirectory(dirIndexPtr, dirEntryPtr, fileNumber, fileName)
  2237.     DirIndexInfo    *dirIndexPtr;
  2238.     Fslcl_DirEntry        *dirEntryPtr;
  2239.     int             fileNumber;
  2240.     char         *fileName;
  2241. {
  2242.     int             nameLength;
  2243.     int             recordLength;
  2244.     int             leftOver;
  2245.     int            oldRecLength;
  2246.  
  2247.     nameLength = strlen(fileName);
  2248.     recordLength = Fslcl_DirRecLength(nameLength);
  2249.  
  2250.     while (dirEntryPtr != (Fslcl_DirEntry *) NULL) {
  2251.     if (dirEntryPtr->fileNumber != 0) {
  2252.         oldRecLength = Fslcl_DirRecLength(dirEntryPtr->nameLength);
  2253.         leftOver = dirEntryPtr->recordLength - oldRecLength;
  2254.         if (leftOver >= recordLength) {
  2255.         dirEntryPtr->recordLength = oldRecLength;
  2256.         dirEntryPtr = 
  2257.             (Fslcl_DirEntry *) ((int) dirEntryPtr + oldRecLength);
  2258.         dirEntryPtr->recordLength = leftOver;
  2259.         dirIndexPtr->dirOffset += oldRecLength;
  2260.         } else {
  2261.         dirEntryPtr = NextDirEntry(dirIndexPtr, dirEntryPtr);
  2262.         continue;
  2263.         }
  2264.     } else if (dirEntryPtr->recordLength < recordLength) {
  2265.         dirEntryPtr = NextDirEntry(dirIndexPtr, dirEntryPtr);
  2266.         continue;
  2267.     }
  2268.  
  2269.     dirEntryPtr->fileNumber = fileNumber;
  2270.     dirEntryPtr->nameLength = nameLength;
  2271.     (void)strcpy(dirEntryPtr->fileName, fileName);
  2272.     leftOver = dirEntryPtr->recordLength - recordLength;
  2273.     if (leftOver > FSLCL_DIR_ENTRY_HEADER) {
  2274.         dirEntryPtr->recordLength = recordLength;
  2275.         dirEntryPtr =(Fslcl_DirEntry *) ((int) dirEntryPtr + recordLength);
  2276.         dirEntryPtr->fileNumber = 0;
  2277.         dirEntryPtr->recordLength = leftOver;
  2278.         dirIndexPtr->dirOffset += recordLength;
  2279.     } else {
  2280.         dirEntryPtr = NextDirEntry(dirIndexPtr, dirEntryPtr);
  2281.     }
  2282.     return(dirEntryPtr);
  2283.     }
  2284.  
  2285.     fprintf(stderr, "Directory full.\n");
  2286.     exit(1);
  2287. }
  2288.  
  2289.  
  2290. /*
  2291.  *----------------------------------------------------------------------
  2292.  *
  2293.  * MakeDevices --
  2294.  *
  2295.  *    Add devices to the dev directory.
  2296.  *
  2297.  * Results:
  2298.  *    None.
  2299.  *
  2300.  * Side effects:
  2301.  *    Devices added to the dev directory.
  2302.  *
  2303.  *----------------------------------------------------------------------
  2304.  */
  2305. void
  2306. MakeDevices()
  2307. {
  2308.     FILE        *fp;
  2309.     Fslcl_DirEntry        *dirEntryPtr;
  2310.     DirIndexInfo    indexInfo;
  2311.     char        fileName[FS_MAX_NAME_LENGTH];
  2312.     int            devType;
  2313.     int            devUnit;
  2314.     int            devPermissions;
  2315.     char        buf[FS_MAX_NAME_LENGTH];
  2316.     Fsdm_FileDescriptor    fileFD;
  2317.  
  2318.     fp = fopen(devFileName, "r");
  2319.     if (fp == NULL) {
  2320.     perror(devFileName);
  2321.     exit(1);
  2322.     }
  2323.  
  2324.     dirEntryPtr = OpenDir(devFDPtr, &indexInfo);
  2325.     if (dirEntryPtr == (Fslcl_DirEntry *)NULL) {
  2326.     fprintf(stderr, "MakeDevices: Dev is bogus\n");
  2327.     exit(1);
  2328.     }
  2329.     while (fgets(buf, FS_MAX_NAME_LENGTH, fp) != NULL) {
  2330.     if (sscanf(buf, "%s %d %d %o", fileName, &devType, &devUnit,
  2331.         &devPermissions) != 4) {
  2332.         continue;
  2333.     }
  2334.     MarkFDBitmap(freeFDNum, fdBitmapPtr);
  2335.     ReadFileDesc(freeFDNum, &fileFD);
  2336.     InitDesc(&fileFD, FS_DEVICE, 0, devType, devUnit, 0, 0,
  2337.         devPermissions, curTime.tv_sec);
  2338.     dirEntryPtr = AddToDirectory(&indexInfo, dirEntryPtr, freeFDNum,
  2339.                      fileName);
  2340.     if (!printOnly) {
  2341.         WriteFileDesc(freeFDNum, &fileFD);
  2342.     }
  2343.     printf("Device: %s, %d, %d 0%o\n",
  2344.         fileName, devType, devUnit, devPermissions);
  2345.  
  2346.     summaryPtr->numFreeFileDesc--;
  2347.     freeFDNum++;
  2348.     if (dirEntryPtr == (Fslcl_DirEntry *)NULL) {
  2349.         fprintf(stderr, "MakeDevices: dev directory is full\n");
  2350.         break;
  2351.     }
  2352.     }
  2353.     CloseDir(&indexInfo);
  2354. }
  2355.  
  2356. #if 0
  2357. /*
  2358.  *----------------------------------------------------------------------
  2359.  *
  2360.  * CopySuperBlock --
  2361.  *
  2362.  *    Copy the super block from the first sector of the disk to
  2363.  *    the first sector of the partition being formatted.
  2364.  *
  2365.  * Results:
  2366.  *    A return code from the I/O.
  2367.  *
  2368.  * Side effects:
  2369.  *    Writes on the zero'th sector of the partition.
  2370.  *
  2371.  *----------------------------------------------------------------------
  2372.  */
  2373. ReturnStatus
  2374. CopySuperBlock(firstPartFID, partFID)
  2375.     int firstPartFID;
  2376.     int partFID;
  2377. {
  2378.     ReturnStatus status;
  2379.     char *block;
  2380.  
  2381.     block = (char *)malloc(DEV_BYTES_PER_SECTOR);
  2382.  
  2383.     status = Disk_SectorRead(firstPartFID, 0, 1, block);
  2384.     if (status != SUCCESS) {
  2385.     return(status);
  2386.     }
  2387.     status = Disk_SectorWrite(partFID, 0, 1, block);
  2388.     return(status);
  2389. }
  2390. #endif
  2391.